<?php

namespace App\Models\Task\SnapTaskAssist;

use App\Models\Task\SnapTasks\Repositories\CountSnapNumberService;
use App\Models\Task\SnapTasks\SnapTask;
use App\Models\User\AcceleratorPacks\UserAcceleratorPack;
use App\Trip\Traits\ModelDateTrait;
use Carbon\Carbon;
use Eloquent;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Throwable;

/**
 * App\Models\Task\SnapTaskAssist\SnapAcceleratorPacks
 *
 * @property int                             $id
 * @property string                          $task_id        抢票任务id
 * @property string                          $user_id        邀请用户id
 * @property string                          $assist_user_id 助力用户id
 * @property int                             $count          助力数量
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property string                          $date           助力日期
 * @method static Builder|SnapAcceleratorPacks newModelQuery()
 * @method static Builder|SnapAcceleratorPacks newQuery()
 * @method static Builder|SnapAcceleratorPacks query()
 * @method static Builder|SnapAcceleratorPacks whereAssistUserId($value)
 * @method static Builder|SnapAcceleratorPacks whereCount($value)
 * @method static Builder|SnapAcceleratorPacks whereCreatedAt($value)
 * @method static Builder|SnapAcceleratorPacks whereDate($value)
 * @method static Builder|SnapAcceleratorPacks whereId($value)
 * @method static Builder|SnapAcceleratorPacks whereTaskId($value)
 * @method static Builder|SnapAcceleratorPacks whereUpdatedAt($value)
 * @method static Builder|SnapAcceleratorPacks whereUserId($value)
 * @mixin Eloquent
 */
class SnapAcceleratorPacks extends Model
{
    use HasFactory, ModelDateTrait;

    const PERSONAL_MAX_ASSIST_COUNT = 5;
    // 每天最大助力次数
    /**
     * 助力状态
     * 0 助力中 1 已助力 2 助力已完成 3 抢票已结束 4 (助力者)已达到最大助力次数
     */
    const ASSIST_STATE_ASSISTING                = 0;
    const ASSIST_STATE_ASSISTED                 = 1;
    const ASSIST_STATE_COMPLETE                 = 2;
    const ASSIST_STATE_SNAP_END                 = 3;
    const ASSIST_STATE_REACH_PERSONAL_MAX_COUNT = 4;
    public    $fillable
                     = [
            "task_id",
            "user_id",
            "assist_user_id",
            "count",
            "date",
        ];
    protected $table = 'snap_accelerator_packs';

    /**
     * @throws Exception|Throwable
     */
    public function assist(SnapTask $task, AcceleratorPack $pack): SnapAcceleratorPacks
    {
        if ($task->getTaskState() >= SnapTask::TASK_STATE_TICKETED) {
            throw new Exception("当前订单抢票结束，无需助力");
        }

        if ($task->getUserId() == $pack->getUserId()) {
            throw new Exception("温馨提示：抱歉，不可为本人订单加速");
        }
        $today_assisted_count = $this->userTodayAssistCount($pack->getUserId());
        if ($today_assisted_count >= self::PERSONAL_MAX_ASSIST_COUNT) {
            throw new Exception("您当日5次助力已满");
        }

        if ($this->findOneByTaskAndAssistUser($task, $pack->getUserId())) {
            throw new Exception("已帮好友助力成功！谢谢");
        }


        // 自己则不再获取
        if ($task->getAssistCount() > $task::MAX_ASSIST_COUNT || $task->getAssistCount() + $pack->getCount() > $task::MAX_ASSIST_COUNT) {
            throw new Exception("好友已经助力成功！谢谢");
        } else {
            $assist = null;
            DB::transaction(function () use (&$assist, $task, $pack) {
                $assist = $this->create([
                    'user_id'        => $task->getUserId(),
                    'task_id'        => $task->getTaskId(),
                    'assist_user_id' => $pack->getUserId(),
                    'count'          => $pack->getPackageNumber(),
                    'date'           => Carbon::today()->toDateString(),
                ]);
                // 自己获取
                $user_pack      = new UserAcceleratorPack();
                $user_pack_data = [
                    'user_id' => $pack->getUserId(),
                    'channel' => UserAcceleratorPack::CHANNEL_ASSIST,
                    'date'    => Carbon::today()->toDateString(),
                    'count'   => $pack->getCount(),
                ];
                $user_pack->addPack($user_pack_data);
            });

        }
        return $assist;
    }

    public function userTodayAssistCount(string $assist_user_id): int
    {
        // 自己的不算
        return $this->where('assist_user_id', $assist_user_id)
                    ->where('date', Carbon::today()->toDateString())
                    ->where('user_id', '!=', $assist_user_id)
                    ->count();
    }

    public function findOneByTaskAndAssistUser(SnapTask $task, string $assist_user_id): ?self
    {
        return $this->where([
            'task_id'        => $task->getTaskId(),
            'assist_user_id' => $assist_user_id,
        ])->first();
    }

    public function useSelfPacks(SnapTask $task, AcceleratorPack $pack): SnapAcceleratorPacks
    {
        if ($assist = $this->findOneByTaskAndAssistUser($task, $pack->getUserId())) {
            return $assist;
        }

        return $this->create([
            'user_id'        => $task->getUserId(),
            'task_id'        => $task->getTaskId(),
            'assist_user_id' => $pack->getUserId(),
            'count'          => $pack->getPackageNumber(),
            'date'           => Carbon::today()->toDateString(),
        ]);
    }

    public function InviteInfo(SnapTask $task_info, string $assist_user_id): array
    {
        $assist_state = self::ASSIST_STATE_ASSISTING;
        $is_assisted  = $this->findOneByTaskAndAssistUser($task_info, $assist_user_id) ? 1 : 0;
        if ($is_assisted == 1) {
            $assist_state = self::ASSIST_STATE_ASSISTED;
        }

        if ($task_info->getAssistCount() >= SnapTask::MAX_ASSIST_COUNT) {
            $assist_state = self::ASSIST_STATE_COMPLETE;
        }

        if ($task_info->getTaskState() >= SnapTask::TASK_STATE_TICKETED) {
            $assist_state = self::ASSIST_STATE_SNAP_END;
        }

        $person_max_assist_count = self::PERSONAL_MAX_ASSIST_COUNT;
        $today_assisted_count    = $this->userTodayAssistCount($assist_user_id);
        // 如果未助力过 , 就判断是否达到最大助力次数
        if (!$is_assisted) {
            if ($today_assisted_count >= $person_max_assist_count) {
                $assist_state = self::ASSIST_STATE_REACH_PERSONAL_MAX_COUNT;
            }
        }
        $count_snap = new CountSnapNumberService();
        $main       = $task_info
            ->getTrainOrderInfo()
            ?->getMainTrain();
        return [
            "is_self"                 => $task_info->getUserId() == $assist_user_id ? 1 : 0,
            "is_assisted"             => $is_assisted,
            "person_max_assist_count" => $person_max_assist_count,
            "today_assisted_count"    => $today_assisted_count,
            "task_assisted_count"     => $task_info->getAssistCount(),
            "assist_state"            => $assist_state,
            "total_service_count"     => $count_snap->getCount(),
            "train_info"              => [
                'to_name'    => $main?->getToName() ?: '',
                'to_name_uy' => $main?->getToNameUy() ?: '',
            ],
        ];
    }
}
